﻿#include "ssMySQLStmtQuery.h"
#include "dump/ssException.h"


namespace StarSeeker
{

ssMySQLStmtQuery::ssMySQLStmtQuery()
{
}

ssMySQLStmtQuery::~ssMySQLStmtQuery()
{
	StmtExit();
}

void ssMySQLStmtQuery::StmtExit()
{
	m_stmt.Clear();
	std::map<u32, ssMySQLStmt>::iterator itr;
	for (itr=m_stmtMap.begin(); itr!=m_stmtMap.end(); ++itr)
	{
		itr->second.Clear();
	}
	m_stmtMap.clear();
	ssMySQLConnection::Exit();
}

void ssMySQLStmtQuery::Query(const char * pSql, const char * pIn, const char * pOut, u8 resultFlag, i32 num, ...)
{
	if (Connect())
	{
		m_stmt.Clear();
		int ret = m_stmt.PrepareQuery(pIn, pOut, pSql, resultFlag);
		if (ret)
		{
			SS_THROW(m_error)
			return;
		}
		va_list arglist;
		va_start(arglist, num);
		ret = m_stmt.ExecuteQueryVariable(num, arglist);
		va_end(arglist);
		if (ret)
		{
			SS_THROW(m_error)
			return;
		}
	}
	else
	{
		SS_THROW(m_error)
	}
}

void ssMySQLStmtQuery::Query(const char* pSql, const char* pIn, const char* pOut, u8 resultFlag, u32 len, const char* data)
{
	if (Connect())
	{
		m_stmt.Clear();
		int ret = m_stmt.PrepareQuery(pIn, pOut, pSql, resultFlag);
		if (ret)
		{
			SS_THROW(m_error)
			return;
		}
		ret = m_stmt.ExecuteQueryStream(len, data);
		if (ret)
		{
			SS_THROW(m_error)
			return;
		}
	}
	else
	{
		SS_THROW(m_error)
	}
}

void ssMySQLStmtQuery::Transaction()
{
	SS_THROW_IF(!ssMySQLConnection::Transaction(), m_error)
}

void ssMySQLStmtQuery::Commit()
{
	SS_THROW_IF(!ssMySQLConnection::Commit(), m_error)
}

void ssMySQLStmtQuery::Rollback()
{
	SS_THROW_IF(!ssMySQLConnection::Rollback(), m_error)
}

StarSeeker::ssMultiLineBuffer& ssMySQLStmtQuery::GetResultSet()
{
	i64 ret = m_stmt.FormatResult();
	SS_THROW_IF(ret<0, m_error)
	return m_resultSet;
}

StarSeeker::ssMultiLineBuffer& ssMySQLStmtQuery::GetResultSet(u32 id)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		m_error = "GetResultSet id not found!";
		SS_THROW(m_error)
	}
	else
	{
		i64 ret = itr->second.FormatResult();
		SS_THROW_IF(ret < 0, m_error)
	}
	return m_resultSet;
}

StarSeeker::ssWriteBytes& ssMySQLStmtQuery::GetOneResult()
{
	i64 ret = m_stmt.FormatResult();
	SS_THROW_IF(ret < 0, m_error)
	return m_result;
}

StarSeeker::ssWriteBytes& ssMySQLStmtQuery::GetOneResult(u32 id)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		m_error = "GetResultSet id not found!";
		SS_THROW(m_error)
	}
	else
	{
		i64 ret = itr->second.FormatResult();
		SS_THROW_IF(ret < 0, m_error)
	}
	return m_result;
}

void ssMySQLStmtQuery::PrepareQuery(u32 id, const char* pIn, const char* pOut, const char* pSql, const u8 resultFlag)
{
	ssMySQLStmt stmt;
	std::pair<std::map<u32, ssMySQLStmt>::iterator, bool> ret = m_stmtMap.insert(std::pair<u32, ssMySQLStmt>(id, stmt));
	if (ret.second)
	{
		if (Connect())
		{
			(ret.first->second).Init(this);
			int pret = (ret.first->second).PrepareQuery(pIn, pOut, pSql, resultFlag);
			if (pret)
			{
				SS_THROW(m_error)
			}
		}
		else
		{
			SS_THROW(m_error)
		}
	}
}

void ssMySQLStmtQuery::QueryByID(u32 id, i32 num, ...)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return;
	}
	if (!itr->second.IsPrepared())
	{
		m_error = "ssMySQLStmt:IsPrepared false!";
		SS_THROW(m_error)
		return;
	}
	if (Connect())
	{
		va_list arglist;
		va_start(arglist, num);
		int ret = itr->second.ExecuteQueryVariable(num, arglist);
		va_end(arglist);
		if (ret)
		{
			SS_THROW(m_error)
		}
	}
	else
	{
		SS_THROW(m_error)
	}
}

void ssMySQLStmtQuery::QueryByID(u32 id, u32 len, const char* data)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return;
	}
	if (!itr->second.IsPrepared())
	{
		m_error = "ssMySQLStmt:IsPrepared false!";
		SS_THROW(m_error)
			return;
	}
	if (Connect())
	{
		int ret = itr->second.ExecuteQueryStream(len, data);
		if (ret)
		{
			SS_THROW(m_error)
		}
	}
	else
	{
		SS_THROW(m_error)
	}
}

StarSeeker::u8 ssMySQLStmtQuery::GetResultFlag(u32 id)
{
	std::map<u32, ssMySQLStmt>::iterator itr = m_stmtMap.find(id);
	if (itr == m_stmtMap.end())
	{
		return 0;
	}
	else
	{
		return itr->second.GetResultFlag();
	}
}

void ssMySQLStmtQuery::RePrepare()
{
	if (!m_stmtMap.empty())
	{
		std::map<u32, ssMySQLStmt>::iterator itr;
		for (itr = m_stmtMap.begin(); itr != m_stmtMap.end(); ++itr)
		{
			itr->second.Init(this);
			itr->second.ClearResult();
			int pret = itr->second.Prepare();
			if (pret)
			{
				SS_THROW(m_error)
					break;
			}
		}
	}
}

}
